package com.nx.platform.es.bean.modle.score;

import com.google.common.base.Enums;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.nx.platform.es.common.utils.MoreSplitters;
import com.nx.platform.es.common.utils.MoreMaps;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author
 * @since 2016年10月21日
 */
public class NumberTermsFilterParser implements ScoreFunctionFieldConfigParser {

    @Override
    public ImmutableMap<String, ?> parse(Map<?, ?> settings) {
        String fieldName = MoreMaps.getString(settings, "fieldName");
        Preconditions.checkState(!Strings.isNullOrEmpty(fieldName), "param fieldName not found");
        String clazz = MoreMaps.getString(settings, "class");
        String[] values = MoreMaps.getStringArray(settings, "values", MoreSplitters.COMMA);
        if (values == null || values.length == 0) {
            throw new IllegalStateException("param values empty");
        }
        Set<Comparable<? extends Number>> numbers = new HashSet<>(values.length);
        for (String value : values) {
            Comparable<? extends Number> number = parse(clazz, value);
            if (number == null) {
                throw new IllegalStateException("param values incorrect: " + Arrays.toString(values));
            }
            numbers.add(number);
        }
        float weight = MoreMaps.getFloatValue(settings, "weight", 0f);
        ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
        builder.put("fieldName", fieldName);
        builder.put("weight", weight);
        builder.put("values", numbers);
        return builder.build();
    }

    protected Comparable<? extends Number> parse(String clazz, String str) {
        return Enums.getIfPresent(Parsers.class, clazz).or(Parsers.Long).parse(str);
    }

    enum Parsers {
        Byte {
            @Override
            Comparable<? extends Number> parse(String str) {
                try {
                    return java.lang.Byte.parseByte(str);
                } catch (NumberFormatException nfe) {
                    return null;
                }
            }
        },
        Short {
            @Override
            Comparable<? extends Number> parse(String str) {
                try {
                    return java.lang.Short.parseShort(str);
                } catch (NumberFormatException nfe) {
                    return null;
                }
            }
        },
        Integer {
            @Override
            Comparable<? extends Number> parse(String str) {
                return Ints.tryParse(str);
            }
        },
        Long {
            @Override
            Comparable<? extends Number> parse(String str) {
                return Longs.tryParse(str);
            }
        };

        abstract Comparable<? extends Number> parse(String str);

    }

}
